#习题13 创建一个Shape基类，包含一个area方法用于计算形状的面积。然后创建Rectangle和Circle子类，分别实现自己的area方法来计算矩形和圆的面积。
import math


class Shape:
    def area(self):
        raise NotImplementedError('You must implement this method')
    '''
    习题14 在Shape基类中添加一个perimeter方法，并在Rectangle和Circle中实现它。对于Circle，可以将其周长定义为直径乘以π。
    '''
    def perimeter(self):
        raise NotImplementedError('You must implement this method')

    #习题17
    #在Shape基类中定义一个describe方法，它返回一个描述形状类型的字符串。在子类中重写这个方法以返回更具体的描述。
    def describe(self):
        raise NotImplementedError('You must implement this method')

    def calculate_shape_properties(self,shape):
        print(shape.area())
        print(shape.perimeter())

    #习题18
    #使用多态性，创建一个函数describe_shapes，它接受一个或多个Shape类型的参数，并打印出每个形状的描述。
    # def describe_shape(self,shape):
    #     print(shape.describe())

    def describe_shape(self,*shapes):
        '''

        :param shapes:  *shapes可以传入多个参数
        :return:
        '''
        for shape in shapes:
            print(shape.describe())

    def __str__(self):
        raise NotImplementedError('You must implement this method')

    def isinstance(self):
        raise NotImplementedError('You must implement this method')

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    '''
      用来矩形计算
    '''
    def area(self):
        return self.width * self.height

    def perimeter(self):
        perimeter = 2 * (self.width + self.height)
        return perimeter

    def describe(self):
        return 'Rectangle'

    def __str__(self):
        return self.describe()

    def isinstance(self,obj):
        return isinstance(obj,Rectangle)



class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return math.pi * self.radius * self.radius

    def perimeter(self):
        return 2 * math.pi * self.radius

    def describe(self):
        return 'Circle'

    def __str__(self):
        return self.describe()

    def isinstance(self, obj):
        return isinstance(obj, Circle)

#习题16 创建一个Triangle类，也继承自Shape基类，并实现area和perimeter方法。
class Triangle(Shape):
    def __init__(self, a, b, c):
        self.sides = [a,b,c]

    def area(self):
        # 使用海伦公式计算面积
        s = sum(self.sides) / 2
        return (s * (s - self.sides[0]) * (s - self.sides[1]) * (s - self.sides[2])) ** 0.5

    def perimeter(self):
        return sum(self.sides)

    def describe(self):
        return 'Triangle'

    def __str__(self):
        return self.describe()

    def isinstance(self, obj):
        # instance内置函数，用来判断一个实例对象是否是由某一个类(或者它的子类)实例化创建出来的。
        return isinstance(obj, Triangle)

if __name__ == '__main__':
    circle = Circle(5)
    # print(circle.area())
    # print(circle.perimeter())
    rectangle = Rectangle(5, 5)
    # print(rectangle.area())
    # print(rectangle.perimeter())
    triangle=Triangle(5, 5, 5)

    # print(circle)
    # print(rectangle)
    # print(triangle)

    # shape1 = Shape()
    # shape1.calculate_shape_properties(circle)
    # shape1.calculate_shape_properties(rectangle)
    # # shape1.describe_shape(circle)
    # # shape1.describe_shape(rectangle)
    # shape1.describe_shape(circle, rectangle, triangle)

    # 检查 shape1 是否是 Rectangle 的实例
    if isinstance(circle, Circle):
        print("shape1 is an instance of Rectangle.")

    # 检查 shape2 是否是 Shape 的子类实例
    if isinstance(rectangle, Rectangle):
        print("shape2 is an instance of a subclass of Shape.")

    # 检查 shape3 是否是 Circle 的实例（它不应该是）
    if not  isinstance(triangle, Triangle):
        print("shape3 is not an instance of Circle.")

